package io.github.lhdxhl.wechatpay.config;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import io.github.lhdxhl.wechatpay.property.WxPayProperties;
import io.github.lhdxhl.wechatpay.v3.WxPayClient;

import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

@Configuration
@ConditionalOnClass(WechatPayHttpClientBuilder.class)
@EnableConfigurationProperties(WxPayProperties.class)
//@ConditionalOnProperty(prefix = "wechat")
public class WxApiV3PayConfig {

	@Bean
	@ConditionalOnMissingBean
//	@ConditionalOnProperty(prefix = "wechat", name = {"merchant-serial-number", "merchant-private-key"})
	public WechatPay2Credentials wechatPay2Credentials(WxPayProperties properties) {
		System.out.println("wechatPay2Credentials(...) entered.");

		PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(properties.getMchPrivateKey());

		return new WechatPay2Credentials(properties.getMchId(),
				new PrivateKeySigner(properties.getMchSerialNumber(), merchantPrivateKey));
	}

	@Bean
	@ConditionalOnMissingBean
	public CertificatesManager certificatesManager(WxPayProperties properties, WechatPay2Credentials credentials)
			throws GeneralSecurityException, IOException, HttpCodeException {
		System.out.println("certificatesManager(..) entered.");

		CertificatesManager certificatesManager = CertificatesManager.getInstance();

		// 向证书管理器增加需要自动更新平台证书的商户信息
		certificatesManager.putMerchant(properties.getMchId(), credentials,
				properties.getApiV3Key().getBytes(StandardCharsets.UTF_8));

		return certificatesManager;
	}

	@Bean
	@ConditionalOnMissingBean
	public WechatPayHttpClientBuilder wechatPayHttpClientBuilder(WxPayProperties properties,
																 WechatPay2Credentials credentials,
																 CertificatesManager certificatesManager) throws NotFoundException {
		System.out.println("wechatPayHttpClientBuilder(..) entered.");

		WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
				.withCredentials(credentials)
				.withValidator(new WechatPay2Validator(certificatesManager.getVerifier(properties.getMchId())));
		return builder;
	}

	@Bean
	@ConditionalOnMissingBean
	public CloseableHttpClient closeableHttpClient(WechatPayHttpClientBuilder builder) {
		System.out.println("closeableHttpClient() entered.");

		return builder.build();
	}

	@Bean
	@ConditionalOnMissingBean
	public NotificationHandler notificationHandler(WxPayProperties properties, CertificatesManager certificatesManager) throws NotFoundException {
		System.out.println("notificationHandler() entered.");

		return new NotificationHandler(certificatesManager.getVerifier(properties.getMchId()),
				properties.getApiV3Key().getBytes(StandardCharsets.UTF_8));
	}

	@Bean
	public WxPayClient wxPayClient(CloseableHttpClient httpClient, WxPayProperties wxPayProperties){
		return new WxPayClient(httpClient,wxPayProperties);
	}
}
